#!/usr/bin/perl
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 2000,2004 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
#
# @(#)13   1.66   src/csm/install/copycsmpkgs.perl, setup, csm_rameh, rameh0431a 6/28/04 13:09:09

#--------------------------------------------------------------------------------

=head1    copycsmpkgs

	Platform independent install of /csminstall on Linux and AIX managment servers.

        Example:

         copycsmpkgs -p . InstallCSMVersion=1.3.2 InstallDistributionName=SLES \
                          InstallDistributionVersion=8.1 InstallOSName=Linux \
                          InstallPkgArchitecture=i386 
	Notes:  

=cut

#--------------------------------------------------------------------------------

=head3	file header

        the use statements and $ENV stuff


=cut

#--------------------------------------------------------------------------------

use strict;
BEGIN { $::csmpm = $ENV{'CSM_PM'} ? $ENV{'CSM_PM'} : '/opt/csm/pm'; }
use lib $::csmpm;
use File::Path;

# Provides mkpath();
use FindBin qw($Bin);
use lib "$Bin";

use Getopt::Std;
use NodeUtils;
use CSMDefs;
use InstallUtils;

#--------------------------------------------------------------------------------

=head3	initialize

	sets @::COPY_VALID_ATTRS and $::MSGCAT globals

=cut

#--------------------------------------------------------------------------------

sub initialize
{

    $::MSGCAT     = 'csmInstall.cat';
    $::MSGMAPPATH =
      $ENV{'CSM_MSGMAPS'} ? $ENV{'CSM_MSGMAPS'} : '/opt/csm/msgmaps';
    $::MSGSET = 'csminstall';

    @::COPY_VALID_ATTRS = (
                           "InstallCSMVersion",
                           "InstallOSName",
                           "InstallDistributionName",
                           "InstallDistributionVersion",
                           "InstallPkgArchitecture"
                           );
    @::osTypeVersion;

    $::PLTFRM = `uname`;
    chomp($::PLTFRM);

    # read in the OSDefs, but don't set gobals?
    my %OSDefs = ServerUtils->get_OSDefs();

}

#--------------------------------------------------------------------------------

=head3	usage

        Notes:


=cut

#--------------------------------------------------------------------------------

sub usage
{
    MessageUtils->message('I', 'IMsgcopycsmpkgsUsage');

    exit 1;
}

#--------------------------------------------------------------------------------

=head3	getArgs

        Notes:

=cut

#--------------------------------------------------------------------------------

sub getArgs
{
    my $pkgpath = "";
    if (!getopts('p:cvVh')) { &usage; }

    $::command_line = $0;

    if ($::opt_h) { &usage }
    $::COPY_OPT_FLAG = $::opt_c;
    if ($::opt_v || $::opt_V)
    {
        if ($::opt_v) { $::VERBOSE = $::opt_v; }
        if ($::opt_V) { $::VERBOSE = $::opt_V; }

    }
    if ($::opt_p)
    {

        # Packages path
        $pkgpath = $::opt_p;
    }

    if (!($::opt_p)) { &usage; }

    # Handle attr=value arguments
    if (scalar(@ARGV) > 0)
    {
        foreach my $a (@ARGV)
        {

            # Note:  we allow a null value
            my ($attr, $value) = $a =~ /^\s*(\S+?)\s*=\s*(\S*.*)$/;

            # mkrsrc-api needs something for the value
            if (!length($value))
            {
                $value = "''";
            }
            if (!defined($attr))
            {
                MessageUtils->message('W', 'EMsgBAD_ATTR_VAL_FORM');
                &usage;
            }

            my $found = 0;
            foreach my $va (@::COPY_VALID_ATTRS)
            {
                if ($attr eq $va)
                {

                    # Put quotes around the value to protect spaces
                    # or weird chars

                    $::ATTRS{$va} = $value;
                    $found = 1;
                }
            }
            if (!$found) { MessageUtils->message('E1', 'EMsgBAD_ATTR', $attr); }
        }
    }

    # verify the correctness of the attributes
    &checkattrs;

    @::PKGPATH = split(":", $pkgpath);

    foreach my $p (split(":", $pkgpath))
    {

        #gather the subdirectories too
        push @::PKGPATH, (ServerUtils->returnSubdirectory($p));
    }
}

#--------------------------------------------------------------------------------

=head3	checkattrs

        Notes:

=cut

#--------------------------------------------------------------------------------

sub checkattrs
{

    #check if all the attributes are there, if not defined then get the
    #default from Management Server
    if (!($::ATTRS{'InstallOSName'}))
    {
        $::ATTRS{'InstallOSName'} = InstallUtils->get_OSName;
    }
    if (!($::ATTRS{'InstallCSMVersion'}))
    {
        $::ATTRS{'InstallCSMVersion'} =
          InstallUtils->get_CSMVersion("csm\.core");
    }
    if (!($::ATTRS{'InstallDistributionName'}))
    {
        if (($::ATTRS{'InstallOSName'} eq "Linux") && ($::PLTFRM eq "Linux"))
        {
            $::ATTRS{'InstallDistributionName'} =
              InstallUtils->get_DistributionName;
        }
        elsif (($::ATTRS{'InstallOSName'} eq "Linux") && ($::PLTFRM eq "AIX"))
        {
            NodeUtils->message('E1', 'EMsgNoDistributionName');
        }
    }
    if (!($::ATTRS{'InstallDistributionVersion'}))
    {
        if ((($::ATTRS{'InstallOSName'} eq "Linux") && ($::PLTFRM eq "Linux"))
            || (($::ATTRS{'InstallOSName'} eq "AIX") && ($::PLTFRM eq "AIX")))
        {
            $::ATTRS{'InstallDistributionVersion'} =
              InstallUtils->get_DistributionVersion;
        }
        else
        {
            NodeUtils->message('E1', 'EMsgNoDistributionVersion');
        }
    }
    if (!($::ATTRS{'InstallPkgArchitecture'}))
    {
        if (($::ATTRS{'InstallOSName'} eq "Linux") && ($::PLTFRM eq "Linux"))
        {
            $::ATTRS{'InstallPkgArchitecture'} =
              InstallUtils->get_PkgArchitecture;
        }
        elsif (($::ATTRS{'InstallOSName'} eq "Linux") && ($::PLTFRM eq "AIX"))
        {
            NodeUtils->message('E1', 'EMsgNoArch');
        }
    }

    # check for the valid attributes
    if (length($::ATTRS{'InstallCSMVersion'}) == 0)
    {
        NodeUtils->message('E2', 'EMsgNO_CORE_COPY');
    }

    if ($::ATTRS{'InstallOSName'} eq "Linux")
    {
        if ($::ATTRS{'InstallPkgArchitecture'} =~ /i.86/)    #SSS
        {
            $::ATTRS{'InstallPkgArchitecture'} = "i386";
        }
        my $temp_distro =
            $::ATTRS{'InstallDistributionName'} . " "
          . $::ATTRS{'InstallDistributionVersion'};
        if (!grep(/^$temp_distro$/, @::VALID_DISTROS))
        {
            NodeUtils->message('E', 'EMsgUNSUPPORTED_DISTRO',
                               $temp_distro, join(', ', @::VALID_DISTROS));
        }
        else { NodeUtils->message('V', 'IMsgDETECTED_DISTRO', $temp_distro); }
        if (!grep(/^$::ATTRS{'InstallCSMVersion'}$/, @::VALID_CSM_DISTROS))
        {
            NodeUtils->message(
                               'E5',
                               'EMsgUNSUPPORTED_CSM_DISTRO',
                               "CSM" . $::ATTRS{'InstallCSMVersion'},
                               join(', ', @::VALID_CSM_DISTROS)
                               );
        }
        else
        {
            NodeUtils->message(
                               'V',
                               'IMsgDETECTED_CSM_DISTRO',
                               "CSM" . $::ATTRS{'InstallCSMVersion'}
                               );
        }

        $::DISTRO = $temp_distro;
    }
    elsif ($::ATTRS{'InstallOSName'} eq "AIX")
    {

        # copycsmpkgs will no longer be used to copy AIX files.  If Linux nodes are being
        # managed from an AIX management server then the copycsmpkgs command will be used
        # to copy the Linux packages.
        NodeUtils->message('E', 'EMsgCopyingAIXpkgs');
        exit 1;
    }
    else
    {
        NodeUtils->message("E2", 'EMsgINVALID_OSTYPE');
    }

}

#--------------------------------------------------------------------------------

=head3	getPackageList

        Notes:

=cut

#--------------------------------------------------------------------------------

sub getPackageList
{
    %::pkgdefs =
      InstallUtils->get_pkgdefs(
                                $::ATTRS{'InstallOSName'},
                                $::ATTRS{'InstallDistributionName'},
                                $::ATTRS{'InstallDistributionVersion'},
                                $::ATTRS{'InstallPkgArchitecture'},
                                'MgdNode',
                                $::ATTRS{'InstallCSMVersion'}
                                );

    if ($::ATTRS{'InstallOSName'} eq "AIX")
    {
        $::osTypeVersion =
          $::ATTRS{'InstallOSName'} . $::ATTRS{'InstallDistributionVersion'};
        $::INSTALLDIR       = "/csminstall";
        $::INSTALLDIR_CSM   = $::INSTALLDIR . "/csm";    #/csminstall/csm
        $::INSTALLDIR_CSMVR =
            $::INSTALLDIR_CSM . "/"
          . $::ATTRS{'InstallCSMVersion'};               #/csminstall/csm/1.2/
        $::INSTALLDIR_CSMVRBIN =
          $::INSTALLDIR_CSMVR . "/bin";    #/csminstall/csm/1.2/bin

        $::INSTALLDIR_OS =
          $::INSTALLDIR . "/" . $::ATTRS{'InstallOSName'};    #/csminstall/AIX
        $::INSTALLDIR_OSVER =
            $::INSTALLDIR_OS . "/"
          . $::ATTRS{InstallDistributionVersion};    #/csminstall/AIX/5.1
        $::INSTALLDIR_OSCSM = $::INSTALLDIR_OS . "/csm";    #/csminstall/AIX/csm

        $::INSTALLDIR_CSMVER =
            $::INSTALLDIR_OSCSM . "/"
          . $::ATTRS{'InstallCSMVersion'};    #/csminstall/AIX/csm/1.2.0

        $::INSTALLDIR_CSMBIN =
          $::INSTALLDIR_CSMVER . "/bin";      #/csminstall/AIX/csm/1.2.0/bin
        $::INSTALLDIR_CSMPKG =
          $::INSTALLDIR_CSMVER
          . "/packages";    #/csminstall/AIX/csm/1.2.0/packages
        $::INSTALLDIR_CSMRPM =
          $::INSTALLDIR_CSMPKG
          . "/rpms";        #/csminstall/AIX/csm/1.2.0/packages/rpms
        $::INSTALLDIR_CSMINSTLP =
          $::INSTALLDIR_CSMPKG
          . "/installp";    #/csminstall/AIX/csm/1.2.0/packages/installp

        #
        # create package lists
        #

        # List of Open Source Packages that are required on the node
        my @mgdnode_open_srcrpms = (@{$::pkgdefs{opensrc_prereqs}});
        @::opensrc_rpm_prereqs = (@mgdnode_open_srcrpms);

        # Lists of packages that are part of each CSM component
        my @csm_client_packages = (@{$::pkgdefs{csm_packages}});
        @::csm_packages = (@csm_client_packages);

        my @rsct_client_packages = (@{$::pkgdefs{rsct_packages}});
        @::rsct_packages = (@rsct_client_packages);

        # Operating System Prereqs we need for Managed Nodes
        @::os_prereq = (@{$::pkgdefs{os_prereqs}});

    }
    elsif ($::ATTRS{'InstallOSName'} eq "Linux")
    {
        $::osTypeVersion =
            $::ATTRS{'InstallOSName'}
          . $::ATTRS{'InstallDistributionName'}
          . $::ATTRS{'InstallDistributionVersion'};
        $::INSTALLDIR       = "/csminstall";
        $::INSTALLDIR_CSM   = $::INSTALLDIR . "/csm";    #/csminstall/csm
        $::INSTALLDIR_CSMVR =
            $::INSTALLDIR_CSM . "/"
          . $::ATTRS{InstallCSMVersion};                 #/csminstall/csm/1.2/
        $::INSTALLDIR_CSMVRBIN =
          $::INSTALLDIR_CSMVR . "/bin";    #/csminstall/csm/1.2/bin

        $::INSTALLDIR_OS =
            $::INSTALLDIR . "/"
          . $::ATTRS{"InstallOSName"} . "/"
          . $::ATTRS{'InstallDistributionName'};

        #/csminstall/Linux/RedHat
        $::INSTALLDIR_OSVER =
            $::INSTALLDIR_OS . "/"
          . $::ATTRS{InstallDistributionVersion};  #/csminstall/Linux/RedHat/7.0
        $::INSTALLDIR_OSVER_ARCH =
          $::INSTALLDIR_OSVER . "/"
          . $::ATTRS{
            'InstallPkgArchitecture'};    #/csminstall/Linux/Redhat/7.0/i386

        $::INSTALLDIR_OSCSM =
          $::INSTALLDIR_OS . "/csm";      #/csminstall/Linux/RedHat/csm
        $::INSTALLDIR_CSMVER =
            $::INSTALLDIR_OSCSM . "/"
          . $::ATTRS{InstallCSMVersion};    #/csminstall/Linux/RedHat/csm/1.2.0

        my $INSTALLDIR_OS_NAME = $::PREREQS_ATTR{DistributionName};
        if ($::PREREQS_ATTR{DistributionName} =~ /RedHat/)
        {
            $INSTALLDIR_OS_NAME = "RedHat";
        }
        $::INSTALLDIR_OS_NAME_RPMS =
          $::INSTALLDIR_OSVER_ARCH . "/" . $INSTALLDIR_OS_NAME . "/RPMS";

        #/csminstall/Linux/RedHat/7.3/i386/RedHat/RPMS
        $::INSTALLDIR_CSMBIN =
          $::INSTALLDIR_CSMVER . "/bin"; #/csminstall/Linux/RedHat/csm/1.2.0/bin
        $::INSTALLDIR_CSMPKG =
          $::INSTALLDIR_CSMVER
          . "/packages";    #/csminstall/Linux/RedHat/csm/1.2.0/packages

        #
        # create package lists
        #

        # Lists of Open Source Packages that are required on the node
        my @mgdnode_open_srcrpms = (@{$::pkgdefs{opensrc_prereqs}});
        @::opensrc_rpm_prereqs = (@mgdnode_open_srcrpms);

        # Lists of packages that are part of each CSM component
        my @csm_client_packages = (@{$::pkgdefs{csm_packages}});
        @::csm_packages = (@csm_client_packages);

        my @rsct_client_packages = (@{$::pkgdefs{rsct_packages}});
        @::rsct_packages = (@rsct_client_packages);

        # No need of  director if the OS is AIX
        if ($::PLTFRM eq "Linux")
        {
            @::director_packages = (@{$::pkgdefs{director_packages}});
        }
        else
        {
            @::director_packages = ();
        }

        # Operating System Prereqs for Managed Nodes
        @::os_prereq = (@{$::pkgdefs{os_prereqs}});

        # get sis packages
        #if ( !($::ATTRS{'InstallPkgArchitecture'}  =~ /ppc64/) )
        #{
        #    if( $::DISTRO =~ /SLES/ || $::DISTRO =~ /SuSE/ )
        #    {
        #	      @::sis_packages = (@{$::pkgdefs{sis_packages}});
        #    }
        #}
        # Populate the version release of definition hash
        #foreach my $tmp_var_rpm (@::opensrc_rpm_prereqs, @::csm_packages, @::rsct_packages, @::director_packages, @::os_prereq, @::sis_packages)
        foreach my $tmp_var_rpm (
                                 @::opensrc_rpm_prereqs, @::csm_packages,
                                 @::rsct_packages,       @::director_packages,
                                 @::os_prereq
          )
        {
            my ($my_version, $my_release) =
              split(/::/, InstallUtils->get_definition_version($tmp_var_rpm));
            my @parts = split /-/, $tmp_var_rpm;
            my $basename = shift @parts;
            my $p;
          BNAME: while ($p = shift @parts)
            {
                if ($p !~ m/^\d/)
                {    #if it doesn't start with a digit
                    $basename .= "-$p";
                }
                else { unshift @parts, $p; last BNAME; }
            }
            my $tmp_var1;
            my $my_rindex = rindex($basename, "*");
            if ($my_rindex != -1)
            {
                $tmp_var1 = substr($basename, 0, rindex($basename, "*"));
            }
            else { $tmp_var1 = $basename; }
            $my_rindex = rindex($tmp_var1, "-");
            if (($my_rindex + 1) == 0) { $basename = $tmp_var1; }
            elsif (($my_rindex + 1) == length($tmp_var1))
            {
                $basename = substr($tmp_var1, 0, rindex($tmp_var1, "*"));
            }
            else { $basename = $tmp_var1; }

            $::PackageVersionName{$basename}{'Version'}  = $my_version;
            $::PackageVersionName{$basename}{'Release'}  = $my_release;
            $::PackageVersionName{$basename}{'FullName'} = $tmp_var_rpm;
        }

    }
    else
    {
        NodeUtils->message("E2", 'EMsgINVALID_OSTYPE');
    }
}

#--------------------------------------------------------------------------------

=head3	create_directory_structure

        Notes:

=cut

#--------------------------------------------------------------------------------

sub create_directory_structure
{
    NodeUtils->message('I', 'IMsgCreatingDirectories');
    mkpath($::INSTALLDIR_CSMVRBIN, $::VERBOSE, 0755);
    mkpath($::INSTALLDIR_CSMBIN,   $::VERBOSE, 0755);
    mkpath($::INSTALLDIR_CSMPKG,   $::VERBOSE, 0755);

    if ($::ATTRS{'InstallOSName'} eq "AIX")
    {
        mkpath($::INSTALLDIR_CSMRPM,    $::VERBOSE, 0755);
        mkpath($::INSTALLDIR_CSMINSTLP, $::VERBOSE, 0755);
    }
    elsif ($::ATTRS{'InstallOSName'} eq "Linux")
    {
        InstallUtils->createRPMSdir(
                                    $::ATTRS{'InstallOSName'},
                                    $::ATTRS{'InstallDistributionName'},
                                    $::ATTRS{'InstallDistributionVersion'},
                                    $::ATTRS{'InstallPkgArchitecture'}
                                    );

    }
    else
    {
        NodeUtils->message('E2', 'EMsgINVALID_OSTYPE');
    }
}

#--------------------------------------------------------------------------------

=head3	Main

=cut

#--------------------------------------------------------------------------------

{    # main

    # initialize runtime env
    &initialize;

    # Check the arguments
    &getArgs;

    # get the packege list that needs to be copied
    &getPackageList;

    #Create the destination directories
    &create_directory_structure;

    # get version/release of rpms in /csminstall
    InstallUtils->get_csminstall_pathVersion();

    # Copy the packages to the destination directories

    # find rpms in the -p flag paths
    InstallUtils->search_csm();
    InstallUtils->search_opensrc_prereqs();

    # handle force copy flag
    if ($::COPY_OPT_FLAG)
    {
        if (scalar(@::RpmsNotFoundInCmdPath) >= 1)
        {
            NodeUtils->message('E1', 'EMsgNoRpmFound',
                               join(", ", @::RpmsNotFoundInCmdPath));
        }
        else
        {
            InstallUtils->create_rpm_list_to_copy();
            if (scalar(@::Rpms_not_found) >= 1)
            {
                NodeUtils->message('E1', 'EMsgNoRpmFound',
                                   join(", ", @::Rpms_not_found));
            }
            else
            {
                NodeUtils->message('I', 'IMsgCopyingRpms',
                                   "CSM, RSCT, Director and Open Source");
                ArchiveUtils->copy_rpm();
            }
        }
    }
    else
    {
        InstallUtils->create_rpm_list_to_copy();
        if (scalar(@::Rpms_not_found) >= 1)
        {

            #check for the rpms to be ignored
            my @rpm_ignored     = ();
            my @rpm_not_ignored = ();
            foreach my $rpm_name (@::Rpms_not_found)
            {
                if (   ($rpm_name =~ m/autoupdate/)
                    || ($rpm_name =~ m/perl-libnet/)
                    || ($rpm_name =~ m/perl-DBI/)
                    || ($rpm_name =~ m/perl-XML-Parser/)
                    || ($rpm_name =~ m/perl-XML-Simple/)
                    || ($rpm_name =~ m/fping/))
                {
                    push(@rpm_ignored, $rpm_name);
                }
                else { push(@rpm_not_ignored, $rpm_name); }
            }
            @::Rpms_not_found = @rpm_not_ignored;
            if (scalar(@rpm_ignored) >= 1)
            {
                NodeUtils->message('I', 'IMsgMissingRPM',
                                   join(", ", @rpm_ignored));
            }
            if (scalar(@::Rpms_not_found) > 0)
            {
                NodeUtils->message('E1', 'EMsgNoRpmFound',
                                   join(", ", @::Rpms_not_found));
            }
            NodeUtils->message('I', 'IMsgCopyingRpms',
                               "CSM, RSCT, Director and Open Source");
            ArchiveUtils->copy_rpm();
        }
        else
        {
            NodeUtils->message('I', 'IMsgCopyingRpms',
                               "CSM, RSCT, Director and Open Source");
            ArchiveUtils->copy_rpm();
        }
    }

    #Search for the distro rpms
    InstallUtils->search_copy_distro_rpms();

    # Copy the 'binaries' needed for install to /csminstall/csm
    # We need to copy the binaries here in copycsmpkgs as well as in installms
    # because in a mixed-architecture Linux cluster (xLinux and pLinux), installms
    # would have only copied the binaries for the management server's architecture.
    #

    MessageUtils->message('I', 'IMsgCOPYING_CSMBINARIES');

    ServerUtils->copyBinaries(
                        $::ATTRS{'InstallOSName'},
                        $::ATTRS{'InstallDistributionName'},
                        $::ATTRS{'InstallDistributionVersion'},
                        $::ATTRS{'InstallPkgArchitecture'},
                        $::ATTRS{'InstallCSMVersion'},
                        );


    exit 0;


    #if( $::DISTRO =~ /SLES/ || $::DISTRO =~/SuSE/ ) {
    #       &copy_sis_rpms;
    #}

} # main

